package com.sne.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sne.common.entity.BaseModel;
import com.sne.common.entity.TreeNode;
import com.sne.common.exception.CustomException;
import com.sne.sys.entity.SysDept;
import com.sne.sys.entity.SysUserDept;
import com.sne.sys.mapper.SysDeptMapper;
import com.sne.sys.service.ISysDeptService;
import com.sne.sys.service.ISysUserDeptService;
import com.sne.sys.vo.SysDeptVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 部门 服务实现类
 * </p>
 *
 * @author fanghh
 * @since 2020-01-03
 */
@Service
public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> implements ISysDeptService {

    @Autowired
    private SysDeptMapper sysDeptMapper;

    @Autowired
    private ISysUserDeptService iSysUserDeptService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<TreeNode> findTree() {
        List<TreeNode> topNodeList = sysDeptMapper.selectList(Wrappers.<SysDept>query()
                .lambda()
                .isNull(SysDept::getParentId)
                .orderByAsc(SysDept::getSort))
                .stream().map(x -> {
                    TreeNode treeNode = new TreeNode();
                    treeNode.setId(x.getId());
                    treeNode.setLabel(x.getDeptName());
                    return treeNode;
                }).collect(Collectors.toList());
        this.findChildrenNode(topNodeList);
        return topNodeList;
    }

    private void findChildrenNode(List<TreeNode> topNodeList) {
        topNodeList.forEach(x -> {
            List<TreeNode> treeNodeList = sysDeptMapper.selectList(Wrappers.<SysDept>query()
                    .lambda()
                    .eq(SysDept::getParentId, x.getId())
                    .orderByAsc(SysDept::getSort))
                    .stream().map(dept -> {
                        TreeNode treeNode = new TreeNode();
                        treeNode.setId(dept.getId());
                        treeNode.setLabel(dept.getDeptName());
                        return treeNode;
                    }).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(treeNodeList)) {
                x.setChildren(treeNodeList);
                this.findChildrenNode(treeNodeList);
            }
        });
    }

    @Override
    public void findChildren(List<SysDept> topList, List<SysDept> deptList) {
        topList.forEach(x -> {
            List<SysDept> childrenList = sysDeptMapper.selectList(Wrappers.<SysDept>query()
                    .lambda()
                    .eq(SysDept::getParentId, x.getId())
                    .orderByAsc(SysDept::getSort));
            if (CollectionUtils.isNotEmpty(childrenList)) {
                deptList.addAll(childrenList);
                this.findChildren(childrenList, deptList);
            }
        });
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteByDeptId(Long id) {
        SysDept dept = sysDeptMapper.selectById(id);
        if (Objects.isNull(dept)) {
            throw new CustomException("部门不存在");
        }
        List<SysDept> topList = new ArrayList<>();
        topList.add(dept);
        List<SysDept> deptList = new ArrayList<>(topList);
        findChildren(topList, deptList);
        List<Long> ids = deptList.stream().map(SysDept::getId)
                .collect(Collectors.toList());
        sysDeptMapper.deleteBatchIds(ids);
        iSysUserDeptService.remove(Wrappers.<SysUserDept>query().lambda()
                .in(SysUserDept::getDeptId, ids));
        return Boolean.TRUE;
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteByDeptIds(List<Long> ids) {
        List<SysDept> sysDepts = sysDeptMapper.selectBatchIds(ids);
        if (CollectionUtils.isEmpty(sysDepts)) {
            throw new CustomException("部门不存在");
        }
        List<SysDept> topList = new ArrayList<>(sysDepts);
        List<SysDept> deptList = new ArrayList<>(topList);
        findChildren(topList, deptList);
        List<Long> newIds = deptList.stream().map(SysDept::getId)
                .collect(Collectors.toList());
        sysDeptMapper.deleteBatchIds(newIds);
        iSysUserDeptService.remove(Wrappers.<SysUserDept>query().lambda()
                .in(SysUserDept::getDeptId, newIds));
        return Boolean.TRUE;
    }

    @Override
    public List<SysDeptVO> findList(SysDept dept) {
        LambdaQueryWrapper<SysDept> queryWrapper = Wrappers.<SysDept>query().lambda();
        if(StringUtils.isNoneBlank(dept.getDeptName())){
            queryWrapper.like(SysDept::getDeptName,dept.getDeptName());
        }
        if(dept.getState() != null){
            queryWrapper.eq(SysDept::getState,dept.getState());
        }
        List<SysDept> depts = this.list(queryWrapper
                .orderByAsc(SysDept::getSort).orderByDesc(SysDept::getCreateTime));
        List<SysDeptVO> deptVOS = new ArrayList<>();
        List<Long> ids = depts.stream().map(BaseModel::getId).collect(Collectors.toList());
        depts.forEach(m -> {
            if (!ids.contains(m.getParentId())) {
                SysDeptVO deptVO = new SysDeptVO();
                BeanUtils.copyProperties(m, deptVO);
                deptVOS.add(deptVO);
            }
        });
        depts.removeIf(m -> deptVOS.stream().anyMatch(vo -> vo.getId().equals(m.getId())));
        buildTree(deptVOS,depts);
        return deptVOS;
    }

    @Override
    public List<SysDept> findDeptByUser(Long id) {
        List<SysUserDept> depts = iSysUserDeptService.list(Wrappers.<SysUserDept>query().lambda().eq(SysUserDept::getUserId, id));
        List<Long> ids = depts.stream().map(SysUserDept::getDeptId).collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(ids)){
            return this.list(Wrappers.<SysDept>query().lambda().in(SysDept::getId, ids));
        }
        return null;
    }

    @Override
    public void findChildrenIds(Long deptId,List<Long>ids) {
        List<SysDept> depts = this.list(Wrappers.<SysDept>query().lambda().eq(SysDept::getParentId, deptId));
        if(CollectionUtils.isNotEmpty(depts)){
            depts.forEach(x->{
                this.findChildrenIds(x.getId(),ids);
            });
        }
    }


    private void buildTree(List<SysDeptVO> deptVOS, List<SysDept> depts) {
        deptVOS.forEach(vo -> {
            List<SysDeptVO> deptVOList = depts.stream()
                    .filter(x -> vo.getId().equals(x.getParentId()))
                    .map(x->{
                        SysDeptVO deptVO = new SysDeptVO();
                        BeanUtils.copyProperties(x,deptVO);
                        return deptVO;
                    }).collect(Collectors.toList());
            depts.removeIf(x -> vo.getId().equals(x.getParentId()));
            if (CollectionUtils.isNotEmpty(deptVOList)) {
                vo.setChildren(deptVOList);
                buildTree(vo.getChildren(), depts);
            } else {
                vo.setChildren(new ArrayList<>());
            }
        });
    }

}
